package com.chenl.provider.DEMOS.全局参数校验和异常捕获;

import com.chenl.provider.DTO.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.internal.engine.path.PathImpl;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;

/**
 * @Null :限制只能为null
 * @NotNull :限制必须不为null
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final String SERVICE_EXCEPTION = "服务器开小差啦,请稍后再试~";

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Result<Object> handleError(MethodArgumentTypeMismatchException e){
        log.error("参数类型不匹配:{}",e.getMessage(),e);
        return new Result<>("参数类型不匹配");
    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result<Object> handleError(MissingServletRequestParameterException e){
        log.error("方法请求参数异常:{}",e.getMessage(),e);
        return new Result<>("方法请求参数异常");
    }

    /**
     * 为参数校验异常处理器主要异常
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<Object> handleError(MethodArgumentNotValidException e){
        log.error("参数未通过校验:{}",e.getMessage(),e);
        BindingResult bindingResult = e.getBindingResult();
        List<FieldError> allErrors = bindingResult.getFieldErrors();
        String message="";
        if (allErrors.size()==1){
            FieldError error = allErrors.get(0);
            message+=String.format("%s:%s",error.getField(),error.getDefaultMessage());
        }else {
            for (FieldError error : allErrors) {
                message+=String.format("%s:%s && ",error.getField(),error.getDefaultMessage());
            }
            message=message.substring(0,message.length()-4);
        }
        return new Result<>(message);
    }

    @ExceptionHandler(BindException.class)
    public Result<Object> handleError(BindException e){
        log.error("Bind Exception:{}",e.getMessage(),e);
        FieldError fieldError = e.getFieldError();
        String message=String.format("%s:%s",fieldError.getField(),fieldError.getDefaultMessage());
        return new Result<>(message);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Result<Object> handleError(ConstraintViolationException e){
        log.error("Constraint Exception:{}",e.getMessage(),e);
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        String message="";
        for (ConstraintViolation<?> violation : violations) {
            String path = ((PathImpl) violation.getPropertyPath()).getLeafNode().getName();
             message+=String.format("%s:%s",path,violation.getMessage());
        }

        return new Result<>(message);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Result<Object> handleError(HttpMessageNotReadableException e){
        log.error("Http Message Not Readable Exception:{}",e.getMessage(),e);
        return new Result<>("请求的参数类型与方法接收的参数类型不匹配,请检查!");
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result<Object> handleError(HttpRequestMethodNotSupportedException e){
        log.error("Http Message Method Not Support Exception:{}",e.getMessage(),e);
        return new Result<>(String.format("%s 方法类型不支持%s,请检查!",e.getMessage(),e.getMethod()));
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Result<Object> handleError(HttpMediaTypeNotSupportedException e){
        log.error("Http Media Type Not Support Exception:{}",e.getMessage(),e);
        String message=String.format("不支持%s Content-Type,请检查!",e.getContentType());
        return new Result<>(message);
    }

 /*   @ExceptionHandler(Exception.class)
    public Result<Object> handleError(Exception e){
        log.error("全局异常信息,异常堆栈信息:{}",e.getMessage(),e);
        return new Result<>(SERVICE_EXCEPTION);
    }

    @ExceptionHandler(Throwable.class)
    public Result<Object> handleError(Throwable e){
        log.error("Internal Server Exception:{}",e.getMessage(),e);
        return new Result<>(SERVICE_EXCEPTION);
    }*/

}
